package cn.swenty.backstage.framework.common.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

import org.apache.commons.beanutils.PropertyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ognl.NoSuchPropertyException;
import ognl.Ognl;

public class BeanUtil {
	
	private static Logger log = LoggerFactory.getLogger(BeanUtil.class);
	
	/** 新建一个javabean,将已有对象的所有属性放入该bean内 */
	public static Object create(Object object, Class clazz) {
		Object newObj = null;
		try {
			newObj = clazz.newInstance();
			for (Method set : clazz.getMethods()) {
				if (set.getParameterTypes().length != 1) {
					continue;
				}
				String name = set.getName();
				if (!name.startsWith("set")) {
					continue;
				}
				String getName = "get" + name.substring(3);
				Object value = null;
				try {
					Method get = object.getClass().getMethod(getName, null);
					value = get.invoke(object, null);
				} catch (NoSuchMethodException ex) {
				}
	
				if (value != null) {
					set.invoke(newObj, value);
				}
			}
			return newObj;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	
	}
	
	public static Object copyProperty(Object obj) {
		Object newObj = null;
		try {
			newObj = obj.getClass().newInstance();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		copyProperty(obj, newObj);
		return newObj;
	}
	
	/** 获得属性值 */
	public static Object getValue(Object obj, String expression) {
		try {
			if (obj == null) {
				return null;
			}
			return PropertyUtils.getProperty(obj,expression);
			//return Ognl.getValue(expression, obj);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	/** 将list转为map */
	public static Map toMap(Collection list, String idName) {
		if (list == null) {
			return new HashMap();
		}
		Map map = new HashMap();
		for (Object o : list) {
			try {
				Object id = getValue(o,idName);
				map.put(id, o);
			} catch (Exception e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
		return map;
	}
	
	/** 将一个对象的属性部分复制到另一个对象 */
	public static void copyTo(Object from, Object to, String[] fields) {
		try {
			for (String expression : fields) {
				Object value = Ognl.getValue(expression, from);
				Ognl.setValue(expression, to, value);
			}
		} catch (Exception ex) {
			throw new RuntimeException(ex);
		}
	
	}
	
	/** 将一个对象的属性全部复制到另一个对象 */
	public static void copyFieldsTo(Object from, Object to) {
		Set<String> getFields = BeanUtil.getGetFields(from.getClass());
		Set<String> fields=new HashSet<String>();
		
		for (Method method : to.getClass().getMethods()) {
			String methodName = method.getName();
			if (methodName.startsWith("set")) {
				String name = StringUtil.getFieldName(method.getName());
				if(getFields.contains(name)){
					fields.add(name);
				}
				
			}
		}
		try {
			for (String expression : fields) {
				Object value = Ognl.getValue(expression, from);
				Ognl.setValue(expression, to, value);
			}
		} catch (Exception ex) {
			throw new RuntimeException(ex);
		}
	
	}
	
	/** 将一个对象的属性全部复制到另一个对象 */
	public static void copyAvaiFieldsTo(Object from, Object to) {
		List<String> fields = new ArrayList<String>();
		for (Method method : to.getClass().getMethods()) {
			String methodName = method.getName();
			if (methodName.startsWith("set")) {
				String name = StringUtil.getFieldName(method.getName());
				fields.add(name);
			}
		}
		try {
			for (String expression : fields) {
				try {
					Object value = Ognl.getValue(expression, from);
					Ognl.setValue(expression, to, value);
				} catch (Exception ex) {
				}
			}
		} catch (Exception ex) {
			throw new RuntimeException(ex);
		}
	
	}
	
	/**
	 * 将一个对象的属性全部复制到另一个对象 只拷贝属性,不拷贝集合和自定义对象,如果属性值为null则跳过
	 */
	public static void copyProperty(Object from, Object to) {
		List<String> fields = new ArrayList();
		for (Method method : to.getClass().getMethods()) {
			String methodName = method.getName();
			if (methodName.startsWith("set") && !methodName.equals("set")) {
				String name = StringUtil.getFieldName(method.getName());
				fields.add(name);
			}
		}
		try {
			for (String expression : fields) {
	
				Object value = null;
				try {
					value = Ognl.getValue(expression, from);
				} catch (NoSuchPropertyException ex) {
				}
	
				if (value == null || !JavaTypeUtil.isSimple(value)) {
					continue;
				}
	
				Ognl.setValue(expression, to, value);
			}
		} catch (Exception ex) {
			throw new RuntimeException(ex);
		}
	
	}
	
	/** 为某个list设值 */
	public static void setListField(List list, String name, String value) {
		try {
			for (Object o : list) {
				Ognl.setValue(name, o, value);
			}
		} catch (Exception ex) {
			throw new RuntimeException(ex);
		}
	}
	
	/** 这只对象某个属性值 */
	public static void setField(Object o, String name, Object value) {
		try {
	
			Ognl.setValue(name, o, value);
	
		} catch (Exception ex) {
			throw new RuntimeException(ex);
		}
	}
	
	public static boolean hasMethodName(Object obj, String name) {
		for (Method method : obj.getClass().getMethods()) {
			if (method.getName().equals("name")) {
				return true;
			}
		}
		return false;
	}
	
	/** 根据属性和值筛选出第一个符合的对象 */
	public static Object filter(List list, String filed, Object fieldValue) {
		if(list==null){
			return null;
		}
		for (Object o : list) {
			Object value = BeanUtil.getValue(o, filed);
			if (value == null || fieldValue == null) {
				continue;
			}
			if (fieldValue.equals(value)) {
				return o;
			}
		}
		return null;
	}
	
	public static Object copy(Object obj) {
		try {
			// 将对象写到流里
			ByteArrayOutputStream bo = new ByteArrayOutputStream();
			ObjectOutputStream oo = new ObjectOutputStream(bo);
			oo.writeObject(obj);
			// 从流里读出来
			ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
	
			ObjectInputStream oi = new ObjectInputStream(bi);
			return (oi.readObject());
		} catch (Exception ex) {
			throw new RuntimeException(ex);
		}
	
	}
	
	/** 将一个对象转换为map */
	public static Map toMap(Object obj) {
		Map map = new HashMap();
		List<String> fields = getFileds(obj.getClass());
		try {
			for (String expression : fields) {
	
				Object value = null;
				try {
					 PropertyUtils.getProperty(obj,expression);
					//value = Ognl.getValue(expression, obj);
				} catch (Exception ex) {
				}
				map.put(expression, value);
			}
		} catch (Exception ex) {
			throw new RuntimeException(ex);
		}
		return map;
	}
	
	/** 获得一个字段的所有属性 */
	public static List<String> getFileds(Class clazz) {
		Set<String> setFields = getSetFields(clazz);
		List<String> fields = new ArrayList();
		for (Method method : clazz.getMethods()) {
			String methodName = method.getName();
			if (method.getParameterTypes().length != 0) {
				continue;
			}
			if (methodName.startsWith("get") && !methodName.equals("get")) {
				String name = StringUtil.getFieldName(method.getName());
				if (setFields.contains(name)) {
					fields.add(name);
				}
			}
		}
		return fields;
	}
	
	/** 获得所有包含get方法 的属性名 */
	public static Set<String> getGetFields(Class clazz) {
		Set<String> fields = new HashSet();
		for (Method method : clazz.getMethods()) {
			String methodName = method.getName();
			if (method.getParameterTypes().length != 0) {
				continue;
			}
			if (methodName.startsWith("get") && !methodName.equals("get")) {
				String name = StringUtil.getFieldName(method.getName());
				fields.add(name);
			}
		}
		return fields;
	}
	
	/** 获得所有包含set方法 的属性名 */
	public static Set<String> getSetFields(Class clazz) {
		Set<String> fields = new HashSet();
		for (Method method : clazz.getMethods()) {
			String methodName = method.getName();
			if (method.getParameterTypes().length != 1) {
				continue;
			}
			if (methodName.startsWith("set") && !methodName.equals("set")) {
				String name = StringUtil.getFieldName(method.getName());
				fields.add(name);
			}
		}
		return fields;
	}
	
	/** 根据类型设置一个类属性 */
	public static void setSimpleValue(Object bean, String name, String value, Class clazz) {
		if (clazz == String.class) {
			BeanUtil.setField(bean, name, value);
			return;
		}
		if (value.equals("")) {
			return;
		}
		if (clazz == Date.class) {
			BeanUtil.setField(bean, name, value);
		} else if (clazz == Integer.class || clazz == int.class) {
			BeanUtil.setField(bean, name, Integer.parseInt(value));
		} else if (clazz == Long.class || clazz == long.class) {
			BeanUtil.setField(bean, name, Long.parseLong(value));
		} else if (clazz == Double.class || clazz == double.class) {
			BeanUtil.setField(bean, name, Double.parseDouble(value));
		} else if (clazz == Float.class || clazz == float.class) {
			BeanUtil.setField(bean, name, Float.parseFloat(value));
		} else if (clazz == Boolean.class || clazz == boolean.class) {
			BeanUtil.setField(bean, name, Boolean.parseBoolean(value));
		}
	}
	
	/** 获得一个类所有字段的类型 */
	public static Map<String, Class> getFieldTypes(Class clazz) {
		Set<String> fields = getSetFields(clazz);
		Map map = new HashMap();
		for (Method method : clazz.getMethods()) {
			String methodName = method.getName();
			if (methodName.startsWith("get") && !methodName.equals("get")) {
				String name = StringUtil.getFieldName(method.getName());
				if (fields.contains(name)) {
					map.put(name, method.getReturnType());
				}
			}
		}
		return map;
	}
	
	public static String showBean(Object obj) {
		return BeanUtil.showBean(obj, false);
	}
	
	/** 根据方法名获得某个类声明的方法，调用此方法的前提是，该类声明的方法没有重载 */
	public Method getDeclaredMethod(Class clazz, String methodName) {
		for (Method method : clazz.getDeclaredMethods()) {
			if (method.getName().equals(methodName)) {
				return method;
			}
		}
		return null;
	}
	
	/** 显示对象内容以 key:value 的形式展示,通常为了打印信息用 */
	public static String showBean(Object obj, boolean format) {
		if (obj == null) {
			return null;
		}
		StringBuilder sb = new StringBuilder();
		if (obj instanceof String) {
			return obj + "";
		}
		
		if (obj instanceof String[]) {
			sb.append("[");
			for (Object bean : (String[]) obj) {
				sb.append(bean + ",");
			}
			sb.delete(sb.length() - 1, sb.length());
			sb.append("]");
			return sb.toString();
		}
		
		
		if (obj instanceof Map) {
			Map map=(Map)obj;
			Set<Entry> set=map.entrySet();
			sb.append("[");
			for (Entry en : set) {
				if(format){
					sb.append(en.getKey() + " : "+showBean(en.getValue(),format));
					sb.append(StringUtil.getLine());
				}else{
					sb.append(en.getKey() + "="+showBean(en.getValue(),format)+",");
				}
				
			}
			sb.delete(sb.length() - 1, sb.length());
			sb.append("]");
			return sb.toString();
		}
	
		if (obj instanceof Collection) {
			sb.append("[");
			for (Object bean : (Collection) obj) {
				sb.append(showBean(bean, format) + ",");
			}
			sb.delete(sb.length() - 1, sb.length());
			sb.append("]");
			return sb.toString();
		}
	
		Collection<String> fields = BeanUtil.getGetFields(obj.getClass());
		// 格式化,添加空格并按字母排序
		if (format) {
			TreeMap<String, String> treeMap = new TreeMap();
	
			int maxLength = 0;
			for (String str : fields) {
				if (str.length() > maxLength) {
					maxLength = str.length();
				}
				treeMap.put(str, str);
			}
			fields = new ArrayList();
			for (String str : treeMap.keySet()) {
				fields.add(StringUtil.appendStr(str, " ", maxLength - str.length()));
			}
		}
	
		for (String field : fields) {
			Object value=null;
			try{
				 value = BeanUtil.getValue(obj, field);
			}catch(Exception ex){
				log.warn(obj+"获得属性出错:"+field+","+ex.getMessage());
			}
			
			// 因为系统里可能不包含Hibernate的jar包,所以对于懒加载的对象要通过反射机制判断是否初始化
			try {
				Class hibernate = Class.forName("org.hibernate.Hibernate");
				Method m = hibernate.getMethod("isInitialized", Object.class);
				boolean init = (Boolean) m.invoke(null, value);
				if (!init) {
					;
					continue;
				}
			} catch (Exception ex) {
				// 如果出错说明系统没加载Hibernate包,跳过懒加载验证
			}
	
			if (StringUtil.isNull(value)) {
				continue;
			}
			if(format){
				sb.append(StringUtil.getLine());
				sb.append(field + ":" + value);
			}else{
				sb.append(",");
				sb.append(field + "=" + value);
			}
			
		}
		return sb.toString();
	}
	
	public interface ToString {
		public String getString();
	}
	
	
	/**将一个序列号对象转换为字符串*/
	public static String toString(Serializable obj){
		ByteArrayOutputStream bo = new ByteArrayOutputStream();
		try{
			ObjectOutputStream oo = new ObjectOutputStream(bo);
			oo.writeObject(obj);
			byte[] b=bo.toByteArray();
			return toString(b);
		}catch(Exception ex){
			throw new RuntimeException(ex);
		}
	
	}
	
	/**将一个字符串还原为序列化对象*/
	public static Object toObject(String str){
		try{
			byte[] b=toByte(str);
			// 从流里读出来
			ByteArrayInputStream bi = new ByteArrayInputStream(b);
			ObjectInputStream oi = new ObjectInputStream(bi);
			return oi.readObject();
		}catch(Exception ex){
			throw new RuntimeException(ex);
		}
	
	}
	
	

	/**设置某个字段的值,只能设置基本类型*/
	public static void setValue(Object target,String field,String value){
		if(target==null){
			throw new RuntimeException("传入的对象为null,无法这只属性"+field);
		}
		//获得该字段的类型
		for(Method method:target.getClass().getMethods()){
			//找setF方法
			String name="set"+StringUtil.firstUp(field);
			if(method.getName().equals(name)){
				//参数个数是一个的
				if(method.getParameterTypes().length==1){
					Class type=method.getParameterTypes()[0];
					//参数类型是简单类型
					if(JavaTypeUtil.isSimple(type)){
						setValue(target,field,value,type);
					}
				}
			}
		}
	}
	 
	/**将字符串设置到对象内,已知类型*/
	public static void setValue(Object target,String field,String value,Class type){
		if(field==null){
			return;
		}
		//string
		if(type==String.class){
			BeanUtil.setField(target, field, value);
		}
		if(field.equals("")){
			return;
		}
		
		//日期
		if(type==Date.class){
			BeanUtil.setField(target, field, DateUtil.toDate(value));
		}else if(type==Long.class||type==long.class){
		//long
			BeanUtil.setField(target, field, Long.parseLong(value));
		//int
		}else if(type==Integer.class||type==int.class){
			BeanUtil.setField(target, field, Integer.parseInt(value));
		//double
		}else if(type==Double.class||type==double.class){
			BeanUtil.setField(target, field, Double.parseDouble(value));
		//float
		}else if(type==Float.class||type==float.class){
			BeanUtil.setField(target, field, Float.parseFloat(value));
		}
	}
	
	/**将一个字符串还原为序列化对象*/
	public static Object toObject(byte[] b){
		try{
			// 从流里读出来
			ByteArrayInputStream bi = new ByteArrayInputStream(b);
			ObjectInputStream oi = new ObjectInputStream(bi);
			return oi.readObject();
		}catch(Exception ex){
			throw new RuntimeException(ex);
		}
	
	}
	
	/**将字节数转换为以逗号分隔的字符串*/
	public static String toString(byte[] bytes){
		StringBuilder sb=new StringBuilder();
		for(int i=0;i<bytes.length;i++){
			sb.append(bytes[i]+",");
		}
		return sb.substring(0,sb.length()-1);
	}
	
	/**将以逗号分隔的字符串转换为字节数组*/
	public static byte[] toByte(String byteStr){
		String[] str=byteStr.split(",");
		byte[] result=new byte[str.length];
		for(int i=0;i<result.length;i++){
			result[i]=Byte.parseByte(str[i]);
		}
		return result;
	}
	
	
	
}

